package com.algernoon.nettydemo.netty.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class TimeServer {

	public void bind(int port) {
		// 配置服务端的NIO线程组(Reactor线程组)
		EventLoopGroup bossGroup = new NioEventLoopGroup(); // 用于服务端接收客户端的连接
		EventLoopGroup workerGroup = new NioEventLoopGroup(); // 用于进行SocketChannel的网络读写
		try {
			// Netty用于启动NIO服务端的辅助启动类，目的是降低服务端的开发复杂度
			ServerBootstrap b = new ServerBootstrap();
			b.group(bossGroup, workerGroup) // 把两个NIO线程组加入到ServerBootstrap中
				.channel(NioServerSocketChannel.class) // 设置创建的channel为NioServerSocketChannel对应于JDK NIO中的ServerSocketChannel类
				.option(ChannelOption.SO_BACKLOG, 1024) // TCP参数设置
				.childHandler(new ChildChannelHandler()); // 绑定I/O事件的处理类ChildChannelHandler
			// 服务启动辅助类配置完成后，绑定监听端口，随后调用同步阻塞方法sync()等待绑定操作完成，返回的ChannelFuture用于异步操作的通知回调
			ChannelFuture f = b.bind(port).sync();
			// 通过f.channel().closeFuture().sync()阻塞，等待服务端链路关闭之后main函数才退出
			f.channel().closeFuture().sync();
		} catch (Exception e) {
		} finally {
			// 优雅退出释放线程池资源
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}

	private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {

		@Override
		protected void initChannel(SocketChannel sc) throws Exception {
			sc.pipeline().addLast(new TimeServerHandler());
		}

	}
	
	public static void main(String[] args) {
		new TimeServer().bind(8080);
	}

}
